;(function(g){

  if(g.wxUser) return false;

  var user = g.wxUser = {
    //groupReg: /\(\{\"groups\":(\[\{.*?\}\])\}\)/m,
    //userReg: /\(\{\"contacts\":(\[\{.*?\}\])\}\)/m,
    taskTimer: null,
    config: null,
    sendErrorMap: {
      "10703": "对方关闭了接收消息",
      "10700": "不能发送，对方不是你的粉丝",
      "10701": "该用户已被加入黑名单，无法向其发送消息",
      "62752": "消息中可能含有具备安全风险的链接，请检查",
      "10704": "该素材已被删除",
      "10705": "该素材已被删除",
      "10706": "由于该用户48小时未与你互动，你不能再主动发消息给他。",
      "-8":    "请输入验证码"
    }

  };

  /**
   * 获取一个groupid的key
   */
  user.getCacheKey = function(groupid)
  {
    if (isNaN(groupid)) {
      return null;
    }
    if (!this.config.appKey) {
      if (wxqf_common.DEBUG) console.log('user.getCacheKey failed: appKey is null');
      return null;
    }

    var m = chrome.runtime.getManifest();
    return 'group_user-'+m.version+'-'+this.config.appKey+'-'+groupid;
  };

  /**
   * 获取一个分组的缓存数据
   */
  user.getCache = function(groupid, cb)
  {
    cb = cb || wxqf_common.loop;
    if (isNaN(groupid)) {
      cb('分组id不能为空');
      return;
    }

    var key = this.getCacheKey(groupid);
    if (!key) {
      cb('生成缓存的key失败');
      return;
    }
    // 单位：分钟
    var userCacheTime = this.config.userCacheTime;
    if (userCacheTime <= 0) {
      cb("您设置了不缓存用户数据");
      return;
    }

    // 获取数据
    chrome.storage.local.get(key, function(ret){
      if(!ret || !ret[key]) {
        cb('未获取到缓存数据');
        return;
      }

      /*try {
        var data = JSON.parse(ret[key]);
      } catch(e) {
        cb('解析缓存数据失败（JSON.parse failed）');
        return;
      }*/

      var data = ret[key];

      // 判断缓存是否过期
      var now = (new Date).getTime();
      if(!data.addTime || now - data.addTime > userCacheTime*60*1000) {
        cb("用户缓存数据已过期，需要重新获取");
        return;
      }

      cb(null, data);
    });

  };

  /**
   * 设置一个缓存数据
   * @如果userList == null，则为删除数据
   */
  user.setCache = function(groupid, userList, cb)
  {
    cb = cb || wxqf_common.loop;
    if (isNaN(groupid)) {
      cb('设置缓存：组id不是一个数字');
      return;
    }

    var key = this.getCacheKey(groupid);
    if(!key) {
      cb('设置缓存：生成缓存的key失败');
      return;
    }

    if(userList === null) {
      chrome.storage.local.remove(key);
      if (wxqf_common.DEBUG) console.log('user.setCache delete data, groupid', groupid);
      cb(null, true);
      return;
    }

    var S = {}, data = {};
    S.addTime  = (new Date).getTime();
    S.userList = userList;
    S.groupid  = groupid;

    /*try {
      S = JSON.stringify(S);
    } catch(e) {
      cb("设置缓存：序列化失败（JSON.stringify failed）");
      return;
    }*/

    data[key] = S;

    chrome.storage.local.set(data, function(){
      cb(null, true);
    });
  };

  /**
   * 获取用户url的文本数据，以正则匹配
   * @param {Int} groupid 分组id
   * @param {Int} num 要获取的用户数量
   * @param {Int} page 分页数
   * @param  {Function} cb [description]
   */
  user.getUserHtml = function(groupid, pageNum, page, cb)
  {
    groupid = groupid || 0;
    pageNum = parseInt(pageNum) || 300;
    page = parseInt(page) || 1;
    var token = wxqf_common.getToken();
    if (!cb) cb = wxqf_common.loop;

    if (!token) return cb('wxqf_common.getToken failed', null);

    var url = wxqf_common.getPageUrl('user', token)
      .replace(/pagesize\=\d+/, 'pagesize='+pageNum)
      .replace(/pageidx\=\d+/, 'pageidx='+(page-1))
      .replace(/groupid\=\d+/, 'groupid='+groupid);

    // 去掉xhr的header
    $.ajax({
      type:"GET",
      beforeSend: function (request){
        request.setRequestHeader('X-Requested-With', {toString: function(){ return ''; }});
      },
      url: url,
      //data: msg,
      //dataType: 'json',
      success: function(data) {
        if (!data) return cb('get html failed');
        cb(null, data);
      },
      error: function(xhr, errTxt, errThrown){
        if (wxqf_common.DEBUG) console.log("user.getUserHtml error: ", xhr, errTxt);
        cb(xhr.status+' '+errTxt);
      }
    });

    return this;
  };

  /**
   * 根据文本获取用户json
   */
  user.getUserList = function(groupid, pageNum, page, cb)
  {
    groupid = groupid || 0;
    pageNum = parseInt(pageNum) || 300;
    page = parseInt(page) || 1;
    if (!cb) cb = wxqf_common.loop;

    var me = this;
    me.getUserHtml(groupid, pageNum, page, function(err, content){

      if (wxqf_common.DEBUG) console.log('user.getUserHtml reutrn groupid='+groupid+' pageNum='+pageNum+' page='+page+' error:', err);

      if(err) {
        return cb(err, {groupid:groupid, pageNum:pageNum, page:page});
      }
      if (!content) {
        return cb('getUserJson failed: content is empty', {groupid:groupid, pageNum:pageNum, page:page});
      }
      // 正则匹配出json
      // {"id":195409335,"nick_name":"李森林","remark_name":"","group_id":0}
      var matches = content.match(me.userReg);
      if (!matches || !matches[1]) {
        cb("get user list failed", {groupid:groupid, pageNum:pageNum, page:page});
        return;
      }

      var jsonMathces = null;
      try{
        // JSON有些时候会出错
        jsonMathces = eval(matches[1]);
        // jsonMathces = JSON.parse(matches[1]);
      } catch(e) {
        if (wxqf_common.DEBUG) console.log('JSON.parse error: ', matches[1]);
      }
      if (!jsonMathces) {
        return cb('json parse error', {groupid:groupid, pageNum:pageNum, page:page});
      }

      // 统一字段名
      var list = [];
      $.each(jsonMathces, function(k, v){
        list.push({
          'id': parseInt(v.id),
          'nick_name': v.nick_name,
          'group_id': v.group_id
        });
      });

      cb(null, {'list':list, groupid:groupid, pageNum:pageNum, page:page});
    });
  };

  /**
   * 获取分组
   */
  user.getGroupList = function()
  {
    var code = wxqf_common.getScriptCode();
    // 正则匹配
    // {"id":0,"name":"未分组","cnt":78}
    var matches = code.match(this.groupReg);
    if (!matches || !matches[1]) {
      return null;
    }

    var jsonMathces = null;
    try {
      // JSON.parse 有些字符没法解析
      jsonMathces = eval(matches[1]);
      //jsonMathces = JSON.parse(matches[1]);
    }catch(e) {
      if (wxqf_common.DEBUG) console.log('JSON.parse error: ', matches[1]);
      return null;
    }

    // 统一字段名
    var groups = [];
    $.each(jsonMathces, function(k, v){
      groups.push({
        'id': parseInt(v.id),
        'name': v.name,
        'num': v.cnt
      });
    });

    return groups;
  };

  /**
   * 获取用户总数
   */
  user.getUserTotal = function()
  {
    var groups = this.getGroupList();
    if (!groups) return 0;
    var num = 0;
    $.each(groups, function(k, v){
      num += v.num;
    });
    return num;
  };

  /**
   * 获取分组信息
   */
  user.getGroupInfo = function(id)
  {
    var groups = this.getGroupList();
    if(!groups) return null;
    for(var i = 0; i < groups.length; i++) {
      if (groups[i].id == id) return groups[i];
    }
    return null;
  };

  /**
   * 获取某组下的所有用户
   */
  user.getGroupUserList = function(groupid, pageNum, cb)
  {
    pageNum = pageNum || 300;
    var groupInfo = this.getGroupInfo(groupid);
    cb = cb || wxqf_common.loop;
    if (!groupInfo) {
      if (wxqf_common.DEBUG) {
        console.log('user.getGroupUserList error: getGroupInfo failed groupid='+groupid);
      }
      return cb('getGroupInfo failed');
    }

    if (groupInfo.num == 0) {
      cb(null, []);
      return;
    }

    var me = this;

    // 此处增加从缓存获取用户
    this.getCache(groupid, function(err, ret){

      if(!err) {
        // 从缓存返回
        wxqfzsLog.log("从缓存获取用户分组数据成功",'success');
        cb(null, ret.userList);
        return;
      }

      wxqfzsLog.log(err, 'error');

      // 继续下面的操作
      var userList = [],
        totalPage = Math.ceil(groupInfo.num / pageNum),
        taskNum = totalPage,
        page = 1,
        failedList = {},
        tasks = [],
        timer = null;

      var groupCB = function(err, data){
        var logTxt = '', logType = '';
        if (err) {
          var key = data.groupid + '#' + data.pageNum + '#' + data.page ;
          if (!failedList[key] || failedList[key] < me.config.retryNum) { // 重复执行3次
            if (!failedList[key]) failedList[key] = 1;
            failedList[key]++;
            setTimeout(function(){
              me.getUserList(data.groupid, data.pageNum, data.page, groupCB);
            }, 1000);
            return;
          }
          logTxt = "失败（"+err+"）";
          logType = 'error';
          if (wxqf_common.DEBUG) console.log('user.getGroupUserList error: '+err);
        } else {
          logTxt = "成功";
          logType = 'success';
          userList = userList.concat(data.list);
        }
        taskNum --;
        wxqfzsLog.log("获取分组数据"+logTxt+"：groupid="+data.groupid+" pageNum="+data.pageNum+" page="+ data.page + " leftTaskNum="+taskNum, logType);
        if (taskNum <= 0) {
          // 设置用户缓存
          me.setCache(data.groupid, userList, function(err, ret){
            if (err) {
              wxqfzsLog.log(err, 'error');
            }
            cb(null, userList);
          });
        }
      };

      // 添加所有任务
      for (var i = 0; i < totalPage; i++) {
        tasks.push({'groupid':groupInfo.id, 'pageNum':pageNum, 'page':i+1});
      }
      if(wxqf_common.DEBUG) {
        console.log('getGroupUserList, groupid, tasks:', groupid, tasks);
      }

      timer = setInterval(function(){
        var task = tasks.shift();
        if (!task) {
          clearInterval(timer);
          return;
        }
        me.getUserList(task.groupid, task.pageNum, task.page, groupCB);
      }, me.config.timePerPage*1000);

    });

  };

  /**
   * 此方法获取所有分组的用户
   * @param {Array|null} forbidGroupIds 不需要获取的分组id
   * @param {Function} cb 回调函数
   */
  user.getAllUserList = function(forbidGroupIds, pageNum, cb)
  {
    var startTime = (new Date).getTime();

    forbidGroupIds = forbidGroupIds || [];
    pageNum = pageNum || 300;

    var userList = [];
    var groups = this.getGroupList();
    if (!groups) return cb('user.getAllUserList error: get groups failed');

    var me = this;
    var taskNum = groups.length;

    $.each(groups, function(k, v){
      // 跳过
      if (forbidGroupIds.indexOf(v.id) != -1) {
        taskNum --;
        return true;
      }
      me.getGroupUserList(v.id, pageNum, function(err, data){
        if (err) {
          if (wxqf_common.DEBUG) console.log('user.getAllUserList error:'+err);
        } else {
          userList[v.id] = data;
        }
        taskNum --;
        if (taskNum <= 0) {
          if (wxqf_common.DEBUG) console.log('user.getAllUserList cost '+((new Date).getTime() - startTime)+ ' ms');
          cb(null, userList);
        }
      });
    });
  };

  /**
   * 发送一条消息
   * @param {Object} msg 包含必须字段的message
   */
  user.sendMessage = function(tofakeid, msg, cb)
  {
    cb = cb || wxqf_common.loop;
    if(!msg || 'object' != typeof msg) {
      return cb('msg is empty');
    }
    if(!tofakeid) {
      return cb('tofakeid is empty.');
    }
    // 设置fakeid
    msg.tofakeid = tofakeid;

    // 设置token
    msg.token = wxqf_common.getToken();
    if(!msg.token) {
      //wxqfzsLog.log("获取urltoken失败", 'error');
      cb("获取urltoken失败");
      return;
    }

    // 随机数字段
    msg.random = Math.random();

    var me = this;
    var url = wxqf_common.getPageUrl('singlesend');
    $.ajax({
      type:"POST",
      beforeSend: function (request){
        request.setRequestHeader("wxqfzs_tofakeid", tofakeid);
        request.setRequestHeader("wxqfzs_token", wxqf_common.getToken());
      },
      url: url,
      data: msg,
      dataType: 'json',
      success: function(json) {
        if (wxqf_common.DEBUG) console.log("user.sendMessage success: json", json);
        // 新的返回格式
        if (json.base_resp) {
          if (json.base_resp.ret != 0) {
            var errTxt = me.sendErrorMap[json.base_resp.ret+''] || '';
            cb(json.base_resp.ret +': '+json.base_resp.err_msg+" "+errTxt);
          } else {
            cb(null, json);
          }
        } else if (json.msg != 'ok') {
          var errTxt = me.sendErrorMap[json.ret+''] || '';
          cb(json.ret +': '+json.msg+" "+errTxt);
        } else {
          cb(null, json);
        }
      },
      error: function(xhr, errTxt, errThrown){
        if (wxqf_common.DEBUG) console.log("user.sendMessage error: ", xhr, errTxt);
        cb(xhr.status+' '+errTxt);
      }
    });
  };

  /**
   * user.doUserTask
   */
  user.doUserTask = function(task)
  {
    // 显示log
    wxqfzsLog.clear().show(task);
    wxqfzsLog.log("开始群发消息");
    wxqfzsLog.log("正在开始获取要发送到的用户列表...");

    var me = this;
    wxqf_common.api('messageSetProgress', {progress: 5}, function(ret){
      if (!ret.result) {
        wxqfzsLog.log("设置任务状态失败...", 'error');
        return false;
      }
      // 首先获取用户
      var groupid   = task.groupid;
      var pageNum   = me.config.pageNum;

      var userListFn = function(err, userList){
        if (err) {
          wxqfzsLog.log("获取用户失败："+err, 'error');
          return false;
        }
        if(!groupid) {
          var tmpUserList = [];
          $.each(userList, function(k, v){
            tmpUserList = tmpUserList.concat(v);
          });
          userList = tmpUserList;
        }
        // post到bg
        wxqf_common.api('messageAddUser', {'userList':userList}, function(ret){
          if (!ret.result) {
            wxqfzsLog.log("获取用户失败："+ret.error, 'error');
            return;
          }
          wxqfzsLog.log("获取待发送的用户完成，总数："+userList.length, 'success');
          // 执行下一步任务
          wxqf_common.api('messageGetDetail', {}, function(ret){
            wxqfzsLog.log("正在执行下一步任务");
            me.doTask(ret.data);
          });
        });
      };

      // 如果传入了userList
      if(task.messageUserList) {
        userListFn(null, task.messageUserList);
        return;
      }

      // 获取所有用户
      if (!groupid) {
        // 排除黑民单
        me.getAllUserList([1], pageNum, userListFn);
      } else {
        me.getGroupUserList(groupid, pageNum, userListFn);
      }

    });
  };

  /**
   * user.doSendTask
   */
  user.doSendTask = function(task)
  {
    // 显示log
    wxqfzsLog.show(task);
    wxqfzsLog.log("正在开始向用户发送消息");
    wxqfzsLog.displayStatus();

    var me = this;

    // 定时器
    clearInterval(me.taskTimer);

    var taskFn = function(ret){
      if(!ret.result) {
        wxqfzsLog.log('获取待发送的用户错误：'+ret.error, 'error');
        if(ret.error_no && ret.error_no == 10001) {
          clearInterval(me.taskTimer);
          wxqfzsLog.log('您已经打开了一个群发窗口，可<a href="javascript:;" id="wxqfzsCloseLogBtn">点击此处关闭此页群发助手状态栏</a>', 'error');
        }
        return;
      }
      // 没有用户，则发送完毕
      if(!ret.user && !ret.detail.runningNum) {
        clearInterval(me.taskTimer);
        if(!$('#wxqfzsCloseLogBtn').length) {
          wxqfzsLog.log('所有用户消息已经发送完毕。<a href="javascript:;" id="wxqfzsCloseLogBtn">点击关闭</a>', 'success');
        }
        return;
      } else if (!ret.user) {
        //wxqfzsLog.log('正在等待其他用户发送完毕', 'info');
        if(wxqf_common.DEBUG) {
          console.log('doSendTask 正在等待其他用户发送完毕');
        }
        return;
      }
      var user    = ret.user;
      var message = ret.detail.message;
      me.sendMessage(user.id, message, function(err, json){
        var result = true;
        if (err) result = false;
        var status = err ? '失败（'+err+'）' : '发送成功';
        var sType  = err ? 'error' : 'success';
        wxqf_common.api('messageCompleteOne', {'result':result, 'user':user}, function(compRet){
          var userName = user.nick_name + "(" + user.id + ")";
          var sentMsg  = "发送状态：" + status + "，任务状态：" + compRet.result + " " + (compRet.error ? compRet.error : '');
          wxqfzsLog.log("--> "+userName+" "+sentMsg, sType);
          wxqfzsLog.displayStatus();
        });
      });
    };

    me.taskTimer = setInterval(function(){
      // 并发发送
      for (var i =0; i < me.config.sendCount; i++) {
        wxqf_common.api('messageGetOne', {}, taskFn);
      }
    }, me.config.sendTime*1000);
  };

  /**
   * 执行任务
   */
  user.doTask = function(task)
  {
    var me = this;

    // 未建立
    if (task.progress == 0) {
      //alert('您还未建立群发消息任务');
      return;
    }

    // 已经完成
    if (task.progress == 15) {
      if (wxqf_common.DEBUG) console.log('当前消息已发送完毕: ', task.groupid, task.message);
      return;
    }

    // 开始获取用户
    if (task.progress == 1 || task.progress == 5) {
      me.doUserTask(task);
      return;
    }

    // 开始发送
    if (task.progress >= 10) {
      me.doSendTask(task);
      return;
    }
  };

})(window);





// 执行
$(function(){

  // 验证hash
  /*var hash = window.location.hash;
  if (hash != '#wxqfzs_send') {
    return false;
  }*/

  // 获取消息详情
  wxqf_common.api('messageGetDetail', {}, function(ret){

    if (wxqf_common.DEBUG) {
      console.log('user->messageGetDetail, ret', ret);
    }
    wxUser.config = ret.data.config;
    wxUser.doTask(ret.data);
  });

  //离开提示
  /*window.onbeforeunload = function () {
    return '你确定要离开此页面？';
  };*/

});